﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;

using FWF.Logging.Statistics;

using log4net.Core;

using NUnit.Framework;

namespace FWF.Logging.Test.Statistics
{
    /// <summary>
    /// 
    /// </summary>
    [TestFixture]
    public class StatCounterTest
    {
        private readonly InMemoryLogger _testLog = new InMemoryLogger();

        /// <summary>
        /// Setups this instance.
        /// </summary>
        [SetUp]
        public void Setup()
        {
            _testLog.Reset();
        }

        /// <summary>
        /// Determines whether [has messages from close].
        /// </summary>
        [Test]
        public void PerformSnapShot()
        {
            // Create a custom counter and supply the testing log implementation
            StatCounter tt = StatCounter.Create( 
                _testLog, 
                "Test", 
                "Test StatCounter #1"
                );

            tt.Increment();
            tt.PerformSnapShot();

            // StatCounter should have written Trace log entries for the PerformSnapShot() method
            IEnumerable<string> listMessages = _testLog.GetMessagesForLog( Level.Trace );

            foreach ( string s in listMessages )
            {
                Debug.WriteLine( s );
            }

            var wrappingCollection = new List<string>( listMessages );

            Assert.IsNotEmpty( wrappingCollection );
            Assert.GreaterOrEqual(
                wrappingCollection.Count,
                1
                );
        }

        /// <summary>
        /// Adds the message.
        /// </summary>
        [Test]
        public void IncrementMaintainsValue()
        {
            // Create a custom counter and supply the testing log implementation
            StatCounter tt = StatCounter.Create(
                _testLog,
                "Test",
                "Test StatCounter #1"
                );

            // Should == 5
            tt.Increment();
            tt.IncrementBy( 6 );
            tt.Decrement();
            tt.Decrement();

            tt.PerformSnapShot();

            // StatCounter should have written Trace log entries for the PerformSnapShot() method
            IEnumerable<string> listMessages = _testLog.GetMessagesForLog( Level.Trace );

            foreach ( string s in listMessages )
            {
                Debug.WriteLine( s );
            }

            var wrappingCollection = new List<string>( listMessages );

            Assert.IsNotEmpty( wrappingCollection );
            Assert.GreaterOrEqual(
                wrappingCollection.Count,
                1
                );
        }

        /// <summary>
        /// Determines whether [has messages from close].
        /// </summary>
        [Test]
        public void BackgroundThreadIsPublishLogs()
        {
            // Create a custom counter and supply the testing log implementation
            StatCounter tt = StatCounter.Create(
                _testLog,
                "Test",
                "Test StatCounter #1",
                TimeSpan.FromMilliseconds( 100 )
                );

            tt.Increment();

            // StatCounter should post snapshot before this sleep method finishes
            Thread.Sleep( 300 );

            // StatCounter should have written Trace log entries for the PerformSnapShot() method
            IEnumerable<string> listMessages = _testLog.GetMessagesForLog( Level.Trace );

            foreach ( string s in listMessages )
            {
                Debug.WriteLine( s );
            }

            var wrappingCollection = new List<string>( listMessages );

            Assert.IsNotEmpty( wrappingCollection );
            Assert.GreaterOrEqual(
                wrappingCollection.Count,
                1
                );
        }

        /// <summary>
        /// Sames the stat counter parameter will have the same instance.
        /// </summary>
        [Test]
        public void SameStatCounterParameterWillHaveTheSameInstance()
        {
            StatCounter statCounter = StatCounter.Create( _testLog, "Category", "Name", TimeSpan.FromSeconds( 1 ), "Instance" );
            StatCounter statCounter2 = StatCounter.Create( _testLog, "Category", "Name", TimeSpan.FromSeconds( 2 ), "Instance" );

            Assert.IsTrue( 
                ReferenceEquals( statCounter, statCounter2 ),
                "Object references must be the same"                
                );
        }

        /// <summary>
        /// Differents the instance name is different component.
        /// </summary>
        [Test]
        public void DifferentInstanceNameIsDifferentComponent()
        {
            StatCounter statCounter = StatCounter.Create( _testLog, "Category", "Name", TimeSpan.FromSeconds( 1 ), "Instance" );
            StatCounter statCounter2 = StatCounter.Create( _testLog, "Category2", "Name2", TimeSpan.FromSeconds( 2 ), "Instance2" );

            Assert.IsFalse(
                ReferenceEquals( statCounter, statCounter2 ),
                "Object references must be the same"
                );
        }




    }
}
